import { getProfile } from "@/api/modules/model/profile";
import { getSchema } from "@/api/modules/model/schema";
import { SchemaItem } from "@/components/JsonSchemaForm/interface";
import BasicInfo from "./../../../components/Sansan/Model/components/BasicInfo";
import Navigation from "./../../../components/Sansan/Model/device/Navigation";

import { Device, GatewayType, ProductModel } from "@/api/interface/iot";
import { getDevice, modifyDevice, saveToProduct, syncDevice, syncGetDevice } from "@/api/modules/iot/device";
import { getProduct, syncFromProduct } from "@/api/modules/iot/product";
import PageHeader from "@/components/Frame/PageHeader";
import SaveClearBtn from "@/components/Frame/save-clear-btn";
import JsonView from "@/components/Sansan/Model/develop/PrviewSchemaJson";
import { ViewTypeTopo } from "@/components/Sansan/Model/product/ViewConfig";
import OnlineStatus from "@/components/Sansan/Status/OnlineStatus";
import { productModel } from "@/enums/dictEnum";
import { MessageType } from "@/enums/messageEnum";
import { useAuthButtons } from "@/hooks/useAuthButtons";
import { useTopo } from "@/hooks/useTopo";
import router from "@/routers";
import { IotStore } from "@/stores/modules/iot";
import { AuthBtns, CommonText, SchemaNodeKey } from "@/utils/constants";
import mittBus from "@/utils/mittBus";
import { confirm, showMsg, showTips } from "@/utils/util";
import { ElMessage } from "element-plus";
import { useRoute } from "vue-router";
import SensorList from "../../../components/Sansan/Model/device/SensorFormList";
import SaveToProduct from "../product/components/SaveToProduct";
import DeviceParam from "./../../../components/Sansan/Model/device/DeviceParam";
import FuncList from "./../../../components/Sansan/Model/device/FuncList";
import SimpleInfo from "./../../../components/Sansan/Model/device/SimpleInfo";
import BasicDialog from "./components/basicInfo/basicDialog";
import { PublicStore } from "@/stores/modules/public";
import { getCurrentInstance, ComponentInternalInstance } from "vue";
export default defineComponent({
	setup() {
		const { proxy } = getCurrentInstance() as ComponentInternalInstance;
		const route = useRoute();
		const iotStore = IotStore();
		let { getTopoServer } = useTopo();
		const publicStore = PublicStore();

		const schemaInfo = ref<SchemaItem>({});
		provide(SchemaNodeKey.schema, schemaInfo);
		const gatewaySchemaInfo = ref<SchemaItem>({});
		provide(SchemaNodeKey.gatewaySchema, gatewaySchemaInfo);
		const prifileInfo = ref<any>({});
		provide(SchemaNodeKey.profile, prifileInfo);
		const gatewayPrifileInfo = ref<any>({});
		provide(SchemaNodeKey.gatewayProfile, gatewayPrifileInfo);
		const detail = reactive({ detail: { type: GatewayType.Device, location: {} } as Device.ResDeviceInfo });
		provide(SchemaNodeKey.detailInfo, detail);
		const disabledMod = ref(true);
		provide(AuthBtns.disabledMod, disabledMod);
		mittBus.on("refreshDeviceDetail", () => {
			init();
		});
		onBeforeUnmount(() => {
			mittBus.off("refreshDeviceDetail");
		});
		const buttonsList = ref<any[]>([]);
		onMounted(async () => {
			await init();
			currNav.value = SchemaNodeKey.basic;
			// 获取页面按钮权限
			buttonsList.value = await useAuthButtons(AuthBtns.iotDevice);
			disabledMod.value = !buttonsList.value.some((item: any) => item.path == AuthBtns.pathMod);
		});
		const init = async () => {
			await initDevice();
			await loadProduct();
			await initProfile();
			await initGatewayProfile();
			await initGatewaySchema();
			await initSchema();
			mittBus.emit("clickRefreshDeviceDetail");
		};
		//初始化设备信息
		const initDevice = async () => {
			let { result, code } = await getDevice({ idSn: route.query.sn });
			if (code == 200) {
				detail.detail = result;
			} else {
				showMsg(proxy?.$t("device_detail.msg.nodata"), MessageType.error);
				if (window.frames.length != parent.frames.length) return;
				timeOut.value = setTimeout(() => {
					router.go(-1);
				}, 3000);
			}
		};
		//未找到设备数据时三秒后返回上级页面
		let timeOut = ref();
		//销毁定时器
		onBeforeUnmount(() => {
			clearInterval(timeOut.value);
			timeOut.value = "";
		});
		const initSchema = async () => {
			const { result, code } = await getSchema({ idSn: route.query.sn });
			if (code == 200) schemaInfo.value = result.schema;
		};
		const initProfile = async () => {
			const { result, code } = await getProfile({ idSn: route.query.sn });
			if (code == 200) prifileInfo.value = result;
		};
		const initGatewaySchema = async () => {
			if (detail.detail.gatewaySn && route.query.sn != detail.detail.gatewaySn) {
				const { result, code } = await getSchema({ idSn: detail.detail.gatewaySn });
				if (code == 200) gatewaySchemaInfo.value = result.schema;
			} else {
				//网关是当前设备
				gatewaySchemaInfo.value = schemaInfo.value;
			}
		};
		const initGatewayProfile = async () => {
			if (detail.detail.gatewaySn && route.query.sn != detail.detail.gatewaySn) {
				const { result, code } = await getProfile({
					idSn: detail.detail.gatewaySn,
					path: `config.subdevice.${route.query.sn}`
				});
				if (code == 200) gatewayPrifileInfo.value = result;
			} else {
				//网关是当前设备
				gatewayPrifileInfo.value = prifileInfo.value;
			}
		};

		const currNav = ref<string>("");
		const basicDialog = reactive({
			title: proxy?.$t("device_detail.dialog_title.modify"),
			visible: false
		});
		const changeNav = (nav: string) => {
			currNav.value = nav;
		};
		const submitBasic = async () => {
			let { success } = await modifyDevice({ ...detail.detail });
			if (success) {
				ElMessage.success(proxy?.$t("device_detail.elmsg.succcess"));
				basicDialog.visible = false;
				initDevice();
			} else {
				ElMessage.error(proxy?.$t("device_detail.elmsg.fail"));
			}
		};

		//按钮事件
		const handleFn = function (fn: String, data?: any) {
			switch (fn) {
				case "saveToProduct":
					saveToProductDialog.formData.id = data.sn;
					saveToProductDialog.formData.name = data.name;
					saveToProductDialog.visible = true;
					break;
				case "sync":
					syncDevice({ idSn: data.sn }).then(res => {
						showTips(res.code, proxy?.$t("device_detail.tips.sync"), res.message);
					});
					break;
				case "syncGet":
					syncGetDevice({ idSn: data.sn }).then(res => {
						showTips(res.code, proxy?.$t("device_detail.tips.sync_get"), res.message);
						init();
					});
					break;
				case "syncFromProduct":
					confirm({ content: proxy?.$t("device_detail.confirm.sync_from_product") }).then(flag => {
						if (!flag) {
							return;
						}
						syncFromProduct({ productModel: data.productModel, sn: data.sn }).then(({ code }) => {
							let ok = showTips(code, proxy?.$t("device_detail.tips.sync_from_product"));
							if (ok) {
								init();
							}
						});
					});
					break;
			}
		};
		const saveToProductDialog = reactive<any>({
			visible: false,
			formData: {
				id: "",
				name: "",
				type: GatewayType.Device
			}
		});
		const submitToProduct = async (data: Device.ReqProduct) => {
			data.idSn = data.id;
			let { code, message } = await saveToProduct(data);
			let ok = showTips(code, proxy?.$t("device_detail.tips.submit_product"), message);
			if (ok) saveToProductDialog.visible = false;
		};

		const showProduct = ref(true);
		const productInfo = ref<Device.ResProduct>({});
		const loadProduct = async () => {
			let res: any;
			if (detail.detail.productModel) {
				//获取设备产品
				res = await getProduct({
					productModel: detail.detail.productModel
				});
			} else if (detail.detail.gatewaySn == productModel.modbus) {
				//设备没有产品，并且设备是modbus接入，则产品默认为modbus
				res = await getProduct({
					productModel: productModel.modbus
				});
			} else if (detail.detail.gatewaySn == productModel.hmp) {
				//设备没有产品，并且设备是hmp接入，则产品默认为hmp
				res = await getProduct({
					productModel: productModel.hmp
				});
			}
			productInfo.value = res?.result || {};
		};

		const category = ref();
		const viewType = computed(() => {
			//设备个性化页面
			let item: any = detail.detail.view?.page?.find(info => Object.values(info)[0] as any);
			let page = (item && Object.values(item)[0]) || {};

			//设备个性化组态
			if (!page.url) {
				let topoId = detail.detail.view?.topo?.[0]?.topoId;
				if (topoId) {
					category.value = ViewTypeTopo;
				}
				page.url = topoId;
			}

			if (!page.url && productInfo.value?.id) {
				//设备没有配置视图，但所属产品有视图，用产品视图
				item = productInfo.value.view?.page?.find(info => Object.values(info)[0] as any);
				page = (item && Object.values(item)[0]) || {};

				//产品组态
				if (!page.url) {
					let topoId = productInfo.value.view?.topo?.[0]?.topoId;
					if (topoId) {
						category.value = ViewTypeTopo;
					}
					page.url = topoId;
				}
			}

			//Hmp设备默认
			if (!page.url && (detail.detail.gatewaySn == GatewayType.HmpGateway || detail.detail.productModel == ProductModel.Hmp)) {
				return "Hmp";
			}
			return page.url;
		});

		// 动态引入 @/components/Sansan/Model/views 路径下所有组件
		// 注意 组件必须要有名字，否则过滤掉
		const modulesFiles = import.meta.glob("@/components/Sansan/Model/views/**/*.tsx", { eager: true });
		const modulesFiles1 = import.meta.glob("@/components/Sansan/Model/views/**/*.tsx");
		let comList = {} as any;
		comList = markRaw(comList);
		Object.keys(modulesFiles).forEach(item => {
			let comp = modulesFiles[item] as any;
			let name = comp.default.name;
			if (name) {
				comList[name] = defineAsyncComponent(modulesFiles1[item] as any);
			}
		});
		const componentEl = ref();
		const componentsList = ref(comList);
		return () => {
			return (
				<div class="minBox" style="width:100%;height:100%">
					{iotStore.isMaxDetail ? null : (
						<>
							<PageHeader
								class="leading-6"
								showBackText={false}
								v-slots={{
									operate: () => {
										return (
											<>
												{viewType.value ? (
													<el-button
														onClick={() => {
															showProduct.value = !showProduct.value;
															!showProduct.value && init();
														}}
													>
														{showProduct.value ? CommonText.configView : CommonText.dataView}
													</el-button>
												) : null}
												{/* 显示模式：配置模式、数据可视化模式 */}
												{viewType.value == "Hmp" && buttonsList.value.find(item => item.path == "sync") ? (
													<>
														{buttonsList.value.some((item: any) => item.path == "sync") ? (
															<el-button
																onClick={() => {
																	componentEl.value?.handleFn?.("sync");
																}}
															>
																{proxy?.$t("device_detail.btn.sync_status")}
															</el-button>
														) : null}
														<el-button onClick={() => componentEl.value?.handleFn?.("config")}>
															{proxy?.$t("device_detail.btn.sync_config")}
														</el-button>
														{buttonsList.value.some((item: any) => item.path == "saveToProduct") ? (
															<el-button onClick={() => handleFn("saveToProduct", detail.detail)}>
																{proxy?.$t("device_detail.tips.submit_product")}
															</el-button>
														) : null}
													</>
												) : (
													<>
														{buttonsList.value
															.filter(
																(item: any) =>
																	item.path != AuthBtns.pathMod &&
																	item.path != AuthBtns.pathDel &&
																	item.path != AuthBtns.pathAdd &&
																	item.path != AuthBtns.pathUpdateLocation &&
																	item.path != AuthBtns.pathStrangeGroup &&
																	item.path != AuthBtns.pathAssignGroup
															)
															.map((item: any) => {
																return (
																	<el-button
																		class="iconfont iconbx-skip-next-circle"
																		onClick={() => handleFn(item.path, detail.detail)}
																	>
																		{item.menuName}
																	</el-button>
																);
															})}
													</>
												)}
												{!disabledMod.value && <SaveClearBtn v-model={basicDialog.visible} onSubmit={() => submitBasic()} />}
											</>
										);
									}
								}}
							>
								<span>{detail.detail.name || detail.detail.sn}</span>
								<OnlineStatus v-model={detail.detail.onlineStatus} class="ml-4 mr-4" />
								<el-link
									class="iconfont iconbx-sync ml-2"
									type="primary"
									onClick={() => {
										init();
									}}
								>
									{proxy?.$t("device_detail.link.refresh")}
								</el-link>
							</PageHeader>

							<SaveToProduct
								title={proxy?.$t("device_detail.dialog_title.savetoproduct")}
								v-model:visible={saveToProductDialog.visible}
								formData={saveToProductDialog.formData}
								onSubmit={(data: Device.ReqProduct) => {
									submitToProduct(data);
								}}
							></SaveToProduct>
						</>
					)}
					<BasicDialog
						title={basicDialog.title}
						v-model:visible={basicDialog.visible}
						detail={detail.detail}
						onSubmit={submitBasic}
					></BasicDialog>
					<div style="height: calc(100% - 50px);overflow: auto;">
						{!viewType.value || !showProduct.value ? (
							<>
								{iotStore.isMaxDetail ? null : (
									<div class="mb-4 p-4 bg-white ">
										{/* 基本信息：名称、分组、网关 */}
										<SimpleInfo visible={basicDialog.visible} />
									</div>
								)}
								<div class="iot-detail-content">
									{/* 导航分类：基本信息、设备参数、设备模型、设备日志 */}
									<Navigation onChange={val => changeNav(val)} />

									<div class="bg-white detail-type-detail">
										{/*基本信息*/}
										{currNav.value == SchemaNodeKey.basic ? <BasicInfo type={GatewayType.Device} onSubmit={submitBasic} /> : null}
										{/*设备配置信息--接入地址、接入端口*/}
										{currNav.value == SchemaNodeKey.config ? <DeviceParam /> : null}
										{/*设备模型*/}
										{currNav.value == SchemaNodeKey.sensor ? <SensorList /> : null}
										{/* 控制功能 */}
										{currNav.value == SchemaNodeKey.funcs ? <FuncList /> : null}
										{/*模型定义*/}
										{currNav.value == SchemaNodeKey.extDevelop ? <JsonView type={GatewayType.Device} /> : null}
									</div>
								</div>
							</>
						) : (
							<>
								{viewType.value ? (
									category.value == ViewTypeTopo ? (
										<iframe
											src={
												`${getTopoServer()}/topo/#/visual/show?id=${viewType.value}&sn=${
													detail.detail.sn
												}&preview=pc-data&token=` + publicStore.token
											}
											frameborder="0"
											style="padding: 0;margin: 0;height: calc(100% - 4px);"
											class="w-full"
										></iframe>
									) : (
										h(componentsList.value[viewType.value], {
											ref: componentEl,
											onReload: init,
											is6210: productInfo.value.model == productModel.ss6210,
											isHmp: productInfo.value.model == productModel.hmp,
											detail: detail.detail
										})
									)
								) : null}
							</>
						)}
					</div>
				</div>
			);
		};
	}
});
